using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
using OpenQuarters.WebQuarters.Utils;
using System.Text;
using OpenQuarters.WebQuarters.Core;
using System.Net;
using System.Reflection;

namespace OpenQuarters.WebQuarters.Core.Web.Areas.CMS.Controllers
{
    public class ModulesController : Controller
    {
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult GetAvailableModules()
        {
            var resp = new List<ModuleInfo>();
            foreach (var module in Module.GetModules())
            {
                if (Core.User.Current.HasPermission(Permissions.Module.CreateInstance.SetValue(module.FullName)))
                {
                    resp.Add(module);
                }
            }
            ViewData.Model = resp.ToJSON();
            return View(Site.Helpers.SharedView.Service);
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult CreateInstance(string id)
        {
            ViewData.Model = "{}";

            // id is fully-qualified Type name
            Type moduleType = GeneralUtils.GetTypeByName(Oracle.Context.Server.UrlDecode(id));
            if (moduleType != null && Core.User.Current.HasPermission(Permissions.Module.CreateInstance.SetValue(moduleType.FullName)))
            {
                var moduleInstance = (Module)Activator.CreateInstance(moduleType);
                var moduleDefinition = moduleInstance.ToDefinition();

                ViewData.Model = new
                {
                    definition = moduleDefinition.ToJSON()
                }.ToJSON();
            }
            return View(Site.Helpers.SharedView.Service);
        }

        public ActionResult GetEditForm(string id)
        {
            ViewData.Model = "";

            // id is fully-qualified Type name
            Type moduleType = GeneralUtils.GetTypeByName(Oracle.Context.Server.UrlDecode(id));
            if (moduleType != null && Core.User.Current.HasPermission(Permissions.Module.Edit.SetValue(moduleType.FullName)))
            {
                StringBuilder sb = new StringBuilder();
                var properties = moduleType.GetProperties().Where(e => e.GetCustomAttributes(typeof(PropertyConfigurationAttribute), true).Count() > 0);

                var translationReferences = new List<string>(new string[] { "Save", "Cancel" });
                foreach (var p in properties)
                {
                    translationReferences.Add(p.Name.StartsWith("json_") ? p.Name.Substring(5) : p.Name);
                }
                var translations = Translation.Get(translationReferences);

                foreach (var p in properties)
                {
                    var attr = (PropertyConfigurationAttribute)p.GetCustomAttributes(typeof(PropertyConfigurationAttribute), true)[0];

                    switch (attr.PropertyType)
                    {
                        case PropertyType.Hidden:
                            sb.Append(attr.GetEditControl(p));
                            break;
                        default:
                            sb.Append(@"
<div class=""formRow"">
  <label>" + translations[p.Name.StartsWith("json_") ? p.Name.Substring(5) : p.Name] + @"</label>
  <span>
    ");

                            sb.Append(attr.GetEditControl(p));

                            sb.Append(@"
    <div class=""cmsClear"">&nbsp;</div>
  </span>
</div>");
                            break;
                    }
                }

                sb.Append(@"
<div class=""submitRow"">
    <input type=""submit"" value=""" + translations["Save"] + @""" class=""saveButton"" />
    <input type=""submit"" value=""" + translations["Cancel"] + @""" class=""cancelButton"" />
    <div class=""cmsClear"">&nbsp;</div>
</div>
<div class=""cmsClear"">&nbsp;</div>");

                ViewData.Model = sb.ToString();
            }
            else
            {
                ViewData.Model = "You do not have permission to edit this module or have been logged out of the system";
            }
            return View(Site.Helpers.SharedView.Service);
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Render(string id)
        {
            Oracle.CurrentControllerContext = this.ControllerContext;
            ViewData.Model = null;
            CMSPage.Current = CMSPage.GetVersionForUser(Request.Form["url"]);

            // id is fully-qualified Type name
            Type moduleType = GeneralUtils.GetTypeByName(Oracle.Context.Server.UrlDecode(id));
            if (moduleType != null && Core.User.Current.HasPermission(Permissions.Module.Edit.SetValue(moduleType.FullName)))
            {
                var module = (Module)GeneralUtils.FromJSON(Request.Form["module"].Base64Decode(), null, moduleType);
                ViewData.Model = new Module[] { module }.ToList();
            }

            return View(Site.Helpers.SharedView.Blank);
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public object MethodHandler(string id)
        {
            string[] args = id.Split(',');

            if (args.Length < 3)
                throw new ArgumentException("The assembly name, module name and method must be passed to the handler seperated by a comma");

            string assemblyName = args[0];
            string moduleName = args[1];
            string method = args[2];

            Assembly assembly = Assembly.Load(assemblyName);
            Type moduleType = GeneralUtils.GetTypeByName(assemblyName + "." + moduleName);
            MethodInfo methodInfo = moduleType.GetMethod(method);
            object response = null;

            //Check the method exists
            if (methodInfo != null)
            {
                response = methodInfo.Invoke(assembly, new object[] { Oracle.Request });
            }

            if (response != null && methodInfo.ReturnType.Name == "JFormResponse`1" && Request.Headers["Accept"] != null && Request.Headers["Accept"].IndexOf("application/json") != -1)
                return response.ToJSON();
            else
            {
                CMSPage.Current = CMSPage.GetVersionForUser(Request.UrlReferrer.PathAndQuery);
                //return View("~/Areas/Site/Views/Home/Index.aspx", CMSPage.Current);
                return Redirect(Request.UrlReferrer.PathAndQuery);
            }
            
        }
    }
}
